﻿using System;
using System.Text;
using System.Text.RegularExpressions;
using Microsoft.Security.Application;

namespace HtmlSanitizer
{
    #region RemoveTagStrategy class
    internal class RemoveTagStrategy : ISanitizeStrategy
    {
        #region SanitizeStrategy Members
        public string Execute(Group tagStart, Group tagEnd, string tag, Group attributes)
        {
            return string.Empty;
        }
        #endregion
    }
    #endregion

    #region EncodeTagStrategy class
    internal class EncodeTagStrategy : ISanitizeStrategy
    {
        #region SanitizeStrategy Members
        public string Execute(Group tagStart, Group tagEnd, string tag, Group attributes)
        {
            StringBuilder builder = new StringBuilder();
            builder.Append(tagStart.Success ? tagStart.Value : "<");
            builder.Append(tag);
            builder.Append(tagEnd.Success ? tagEnd.Value : ">");

            return Microsoft.Security.Application.AntiXss.HtmlEncode(builder.ToString());
        }
        #endregion
    }
    #endregion

    #region SanitizeAttributesStrategy class
    internal class SanitizeAttributesStrategy : ISanitizeStrategy
    {
        #region Private Fields
        private static readonly Regex HtmlAttributeExpression = new Regex(@"
            (?'attribute'\w+)
            (\s*=\s*)
            (""(?'value'.*?)""|'(?'value'.*?)')",
            RegexOptions.Singleline | RegexOptions.IgnorePatternWhitespace | RegexOptions.IgnoreCase | RegexOptions.Compiled);
        #endregion

        #region SanitizeStrategy Members
        public string Execute(Group tagStart, Group tagEnd, string tag, Group attributes)
        {
            StringBuilder builder = new StringBuilder();
            builder.Append(tagStart.Success ? tagStart.Value : "<");
            builder.Append(tag);

            foreach (Capture attribute in attributes.Captures)
            {
                builder.Append(MatchHtmlAttribute(tag, attribute));
            }

            if (tagStart.Success && tagStart.Value == "<" && tag.Equals("a", StringComparison.OrdinalIgnoreCase))
                builder.Append(" rel=\"nofollow\"");

            builder.Append(tagEnd.Success ? tagEnd.Value : ">");

            return builder.ToString();
        }
        #endregion

        #region Private Members
        private static string MatchHtmlAttribute(string tag, Capture capture)
        {
            var output = string.Empty;
            var match = HtmlAttributeExpression.Match(capture.Value);

            var attribute = match.Groups["attribute"].Value;
            var value = match.Groups["value"].Value;

            if (TagsConfiguration.Instance.Tags[tag].Attributes.Contains(attribute))
            {
                switch (attribute)
                {
                    case "src":
                    case "href":
                        if (IsUrl(value))
                            output = string.Format(" {0}=\"{1}\"", attribute, value);
                        else
                            output = string.Format(" {0}=\"{1}\"", attribute, AntiXss.UrlEncode(value));
                        break;
                    default:
                        output = string.Format(" {0}=\"{1}\"", attribute, value);
                        break;
                }
            }

            return output;
        }

        private static bool IsUrl(string Url)
        {
            string strRegex = @"^((ht|f)tp(s?)\:\/\/|~/|/)?([\w]+:\w+@)?(([a-zA-Z]{1}([\w\-]+\.?)*(\.[\w]{2,5})?)(:[\d]{1,5})?)?((/?\w+/)+|/?)(\w+\.[\w]{3,4})?([,]\w+)*((\?\w+=\w+)?(&\w+=\w+)*([,]\w*)*)?";
            Regex re = new Regex(strRegex);

            if (re.IsMatch(Url))
                return (true);
            else
                return (false);
        } 
        #endregion

    }
    #endregion

    #region AddDivTagStrategy class
    internal class AddDivTagStrategy : ISanitizeStrategy
    {

        private Random rand;

        public AddDivTagStrategy()
        {
            rand = new Random();
        }

        #region SanitizeStrategy Members
        public string Execute(Group tagStart, Group tagEnd, string tag, Group attributes)
        {
            StringBuilder builder = new StringBuilder();
            builder.Append(tagStart.Success ? tagStart.Value : "<");
            builder.Append(tag);
            builder.Append(tagEnd.Success ? tagEnd.Value : ">");

            if (tagStart.Value == "<")
            {
                long id = GetNextID();
                builder.Insert(0, string.Format("<div id=\"{0}\" style=\"width:580px; overflow:auto;\" class=\"{1}\">", id, "divcodeadded"));
                builder.Insert(0, "<div><a href=\"#\" onClick=\"SwitchCode('" + id + "'); return false;\"><img src=\"/images/minus.gif\"  style=\"border-width:0px;vertical-align:middle;\" />&nbsp;Código</a></div>");
            }
            else if (tagStart.Value == "</")
            {
                builder.Append("</div>");
            }

            return builder.ToString();
        }

        private long GetNextID()
        {
            return (long)(long.MaxValue * rand.NextDouble());
        }
        #endregion
    }
    #endregion

}



